﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Common;
using CSC440TeamOne.CSC440BusinessService.Interface.Services;
using Microsoft.Practices.CompositeWeb;
using Microsoft.Practices.Unity.Utility;

namespace CSC440TeamOne.CSC440BusinessService.Services
{
    public class DummyService : IBusinessService
    {
        public ISecurityService SecurityService { get; set; }
        public IDataService DataService { get; set; }

        private List<User> userList;
        private List<Question> questionList;

        public DummyService([ServiceDependency]ISecurityService securityService, [ServiceDependency]IDataService dataService)
        {
            userList = new List<User>();

            questionList = new List<Question>();

            SecurityService = securityService;

            DataService = dataService;

            this.questionList = DataService.populateQuestionList(); // Populate during instantiation so the values carry between pages (allows editing)
        }

        public void AddUser(User user)
        {
            userList.Add(user);
        }

        public User FindUserById(string id)
        {
            foreach (User user in userList)
            {
                if (user.EmailAddress == id)
                    return user;
            }

            return null;
        }

        /// <summary>
        /// Sets the help text on a particular question in the questionaire list
        /// </summary>
        /// <param name="questionID">Question ID of the questionaire question</param>
        /// <param name="helpText">HelpText object containing popup values</param>
        public void saveHelpText(int questionID, HelpText helpText)
        {
            // Loop through the questions, when the ID matches, set the help text
            foreach (Question q in this.questionList)
            {
                if (q.QuestionID == questionID)
                {
                    q.HelpText = helpText;
                    break;
                }
            }
        }

        /// <summary>
        /// Fill the local class variable with values.  Will eventually come from database
        /// </summary>
        private void populateQuestionList()
        {
            this.questionList = DataService.populateQuestionList();
        }

        /// <summary>
        /// Returns the full questionaire question list to the controller requesting it
        /// </summary>
        /// <returns>List continaing all questionaire questions</returns>
        public List<Question> LoadAllQuestions()
        {
            return this.questionList;
        }

        /// <summary>
        /// Saves specific questionaire answer to list
        /// </summary>
        /// <param name="questionID">Question ID</param>
        /// <param name="answer">Text of the answer chosen</param>
        public void SaveQuestionaireAnswer(int questionID, string answer)
        {
            foreach (Question q in questionList)
            {
                if (q.QuestionID == questionID)
                {
                    // Checkboxes can have multiple answers, so the answer must be stored in the child control
                    if (q.AnswerControlType == Question.Types.CheckBox)
                    {
                        foreach (Question a in q.ChildItems)
                        {
                            if (a.QuestionText == answer)
                            {
                                a.AnswerText = answer;
                                a.Answered = true;
                            }
                        }
                    }
                    else
                    {
                        // All other question types save in the question header
                        q.AnswerText = answer;
                    }

                    q.Answered = true;

                    break;
                }
            }
        }


        public DailyEntryViewModel LoadDailyEntryViewForCurrentUser()
        {
            Debug.WriteLine("start DummyService.LoadDailyEntryViewForCurrentUser");

            try
            {
                var user = SecurityService.LoadCurrentUser();

                Guard.ArgumentNotNull(user, "user");

                var dailyTrackableHealthParameters = DataService.LoadDailyTrackableHealthParametersForUser(user);

                Guard.ArgumentNotNull(dailyTrackableHealthParameters, "dailyTrackableHealthParameters");

                Debug.WriteLine("end DummyService.LoadDailyEntryViewForCurrentUser");

                return new DailyEntryViewModel()
                {
                    HealthParameters = dailyTrackableHealthParameters
                };
            }
            catch (Exception ex)
            {
                Trace.TraceError(ex.ToString());

                throw;
            }
        }

        public MyProgressViewModel LoadHealthProgressForCurrentUser()
        {
            Debug.WriteLine("start DummyService.LoadHealthProgressForCurrentUser");

            try
            {
                var user = SecurityService.LoadCurrentUser();

                Guard.ArgumentNotNull(user, "user");

                var trackableHealthParameters = DataService.LoadTrackableHealthParameterProgressForUser(user);

                Guard.ArgumentNotNull(trackableHealthParameters, "trackableHealthParameters");

                bool hasMaxTolerance = true, hasMinTolerance = true;//TODO: why did i need these?

                Debug.WriteLine("end DummyService.LoadHealthProgressForCurrentUser");

                return new MyProgressViewModel()
                {
                    TrackableHealthParameters = trackableHealthParameters,
                    HasMaxTolerance = hasMaxTolerance,
                    HasMinTolerance = hasMinTolerance
                };
            }
            catch (Exception ex)
            {
                Trace.TraceError(ex.ToString());

                throw;
            }
        }

        public MyHealthGoalConfigViewModel LoadUserHealthGoalsForCurrentUser()
        {
            Debug.WriteLine("start DummyService.LoadUserHealthGoalsForCurrentUser");

            try
            {
                var user = SecurityService.LoadCurrentUser();

                Guard.ArgumentNotNull(user, "user");

                var healthGoals = DataService.FindHeathGoalsForUser(user);

                Guard.ArgumentNotNull(healthGoals, "healthGoals");

                Debug.WriteLine("end DummyService.LoadUserHealthGoalsForCurrentUser");

                return new MyHealthGoalConfigViewModel()
                {
                    HealthGoals = healthGoals
                };
            }
            catch (Exception ex)
            {
                Trace.TraceError(ex.ToString());

                throw;
            }
        }

        public void SaveHealthConfig(MyHealthGoalConfigViewModel model)
        {
            Guard.ArgumentNotNull(model, "model");

            Debug.WriteLine("start DummyService.SaveHealthConfig");

            try
            {
                var user = SecurityService.LoadCurrentUser();

                Guard.ArgumentNotNull(user, "user");

                var healthGoals = model.ChangedHealthGoals();

                Guard.ArgumentNotNull(healthGoals, "healthGoals");

                if (healthGoals.Any())
                {
                    foreach (var healthGoal in healthGoals)
                    {
                        DataService.SaveUserHealthGoal(user, healthGoal);
                    }
                }
            }
            catch (Exception ex)
            {
                Trace.TraceError(ex.ToString());

                throw;
            }

            Debug.WriteLine("end DummyService.SaveHealthConfig");
        }

        public SubmitRecipeModel getNewRecipeViewModel()
        {
            //throw new NotImplementedException();
            return null;
        }

        public void parse(SubmitRecipeModel model)
        {
            //TODO: parse what?
            //throw new NotImplementedException();
        }

        public ProcessRegistrationModel LoadProcessRegistrationModel()
        {
            //throw new NotImplementedException();
            return null;
        }


        public MyRecipeViewModel LoadMyRecipeViewModelForCurrentUser()
        {
            Recipe rod = new Recipe();
            rod.RecipeID = 12;
            rod.name = "Taco Salad";
            RecipeIngredient taco = new RecipeIngredient();
            Ingredient tacoI = new Ingredient();
            tacoI.name = "taco";
            taco.quantity = 1;
            taco.measurement = "";
            taco.ingredient = tacoI;
            RecipeIngredient salad = new RecipeIngredient();
            Ingredient saladI = new Ingredient();
            saladI.name = "salad";
            salad.quantity = 1;
            salad.measurement = "";
            salad.ingredient = saladI;
            rod.ingredients.Add(taco);
            rod.ingredients.Add(salad);
            rod.directions = "Put taco and salad together.";
            rod.value = 1;

            Recipe r2 = new Recipe();
            r2.RecipeID = 23;
            r2.name = "fadfadsfasdf";
            RecipeIngredient ri1 = new RecipeIngredient();
            Ingredient ri1I = new Ingredient();
            ri1I.name = "asdfasdf";
            ri1.quantity = 1;
            ri1.measurement = "sfasdff";
            ri1.ingredient = ri1I;
            RecipeIngredient ri2 = new RecipeIngredient();
            Ingredient ri2I = new Ingredient();
            ri2I.name = "gesagfd";
            ri2.quantity = 1;
            ri2.measurement = "gsgsdh";
            ri2.ingredient = ri2I;
            rod.ingredients.Add(ri1);
            rod.ingredients.Add(ri2);
            r2.directions = "fasdf sda fa sdf asdf asd fas dfa sdfasd";

            Recipe r3 = new Recipe();
            r3.RecipeID = 34;
            r3.name = "vsadavffsd";
            RecipeIngredient ri3 = new RecipeIngredient();
            Ingredient ri3I = new Ingredient();
            ri3I.name = "usrtrggsg";
            ri3.quantity = 1;
            ri3.measurement = "ysyrrs";
            ri3.ingredient = ri3I;
            RecipeIngredient ri4 = new RecipeIngredient();
            Ingredient ri4I = new Ingredient();
            ri4I.name = "uuisrsg";
            ri4.quantity = 1;
            ri4.measurement = "hhrshrhssdr";
            ri4.ingredient = ri4I;
            r3.ingredients.Add(ri3);
            r3.ingredients.Add(ri4);
            r3.directions = "dasf asd fvr taer t ewf ewafds";
            r3.value = -1;

            MyRecipeViewModel mrvm = new MyRecipeViewModel();
            mrvm.recipeOfTheDay = rod;

            mrvm.favoriteRecipes = new List<Recipe>();
            mrvm.favoriteRecipes.Add(rod);
            mrvm.favoriteRecipes.Add(r2);
            mrvm.favoriteRecipes.Add(r3);

            mrvm.suggestedRecipes = new List<Recipe>();
            mrvm.suggestedRecipes.Add(r3);
            mrvm.suggestedRecipes.Add(rod);

            mrvm.searchResults = new List<Recipe>();
            mrvm.searchResults.Add(rod);
            mrvm.searchResults.Add(r3);
            mrvm.searchResults.Add(r2);
            mrvm.searchResults.Add(r3);

            return mrvm;
        }

        public void saveViewRecipeModel(MyRecipeViewModel model)
        {

        }

        public ToleranceConfigListViewModel LoadToleranceConfigItems()
        {
            Debug.WriteLine("start DummyService.LoadToleranceConfigItems");

            try
            {
                var user = SecurityService.LoadCurrentUser();

                Guard.ArgumentNotNull(user, "user");

                var userRole = user.UserRole;

                Microsoft.Practices.CompositeWeb.Utility.Guard.EnumValueIsDefined(typeof(UserRole), userRole, "userRole");

                IEnumerable<HealthParameter> healthParameters = new HealthParameter[] { };

                Guard.ArgumentNotNull(healthParameters, "healthParameters");

                if (userRole == UserRole.administrator || userRole == UserRole.developer)
                {
                    healthParameters = DataService.LoadAllHealthParameters();

                    Guard.ArgumentNotNull(healthParameters, "healthParameters");
                }

                Debug.WriteLine("end DummyService.LoadToleranceConfigItems");

                return new ToleranceConfigListViewModel()
                {
                    HealthParameters = healthParameters
                };
            }
            catch (Exception ex)
            {
                Trace.TraceError(ex.ToString());

                throw;
            }
        }

        public ToleranceConfigDetailsViewModel LoadHealthParameterByID(int healthParameterID)
        {
            Guard.ArgumentNotNull(healthParameterID, "healthParameterID");

            Debug.WriteLine("start DummyService.LoadHealthParameterByID");

            try
            {
                var user = SecurityService.LoadCurrentUser();

                Guard.ArgumentNotNull(user, "user");

                var userRole = user.UserRole;

                Microsoft.Practices.CompositeWeb.Utility.Guard.EnumValueIsDefined(typeof(UserRole), userRole, "userRole");

                var healthParameter = HealthParameter.Empty;

                var userCanEditHealthParameter = false;

                if (userRole == UserRole.administrator || userRole == UserRole.developer)
                {
                    healthParameter = DataService.FindHealthParameterById(healthParameterID);

                    userCanEditHealthParameter = true;

                    Guard.ArgumentNotNull(healthParameter, "healthParameter");
                }

                Debug.WriteLine("end DummyService.LoadHealthParameterByID");

                return new ToleranceConfigDetailsViewModel()
                {
                    HealthParameter = healthParameter,
                    UserCanEditHealthParameter = userCanEditHealthParameter
                };
            }
            catch (Exception ex)
            {
                Trace.TraceError(ex.ToString());

                throw;
            }
        }

        public void SaveHealthParameterConfig(ToleranceConfigDetailsViewModel model)
        {
            Guard.ArgumentNotNull(model, "model");

            Debug.WriteLine("start DummyService.SaveHealthParameterConfig");

            try
            {
                var healthParameter = model.HealthParameter;

                Guard.ArgumentNotNull(healthParameter, "healthParameter");

                DataService.Update(healthParameter);
            }
            catch (Exception ex)
            {
                Trace.TraceError(ex.ToString());

                throw;
            }

            Debug.WriteLine("end DummyService.SaveHealthParameterConfig");
        }

        public void LoadSubmittedRecipesModel(SubmittedRecipesModel model)
        {
            Recipe rod = new Recipe();
            rod.name = "Taco Salad";
            RecipeIngredient taco = new RecipeIngredient();
            Ingredient tacoI = new Ingredient();
            tacoI.name = "taco";
            taco.quantity = 1;
            taco.measurement = "";
            taco.ingredient = tacoI;
            RecipeIngredient salad = new RecipeIngredient();
            Ingredient saladI = new Ingredient();
            saladI.name = "salad";
            salad.quantity = 1;
            salad.measurement = "";
            salad.ingredient = saladI;
            rod.ingredients.Add(taco);
            rod.ingredients.Add(salad);
            rod.directions = "Put taco and salad together.";
            rod.value = 1;
            rod.RecipeID = 000001;

            Recipe r2 = new Recipe();
            r2.name = "fadfadsfasdf";
            RecipeIngredient ri1 = new RecipeIngredient();
            Ingredient ri1I = new Ingredient();
            ri1I.name = "asdfasdf";
            ri1.quantity = 1;
            ri1.measurement = "sfasdff";
            ri1.ingredient = ri1I;
            RecipeIngredient ri2 = new RecipeIngredient();
            Ingredient ri2I = new Ingredient();
            ri2I.name = "gesagfd";
            ri2.quantity = 1;
            ri2.measurement = "gsgsdh";
            ri2.ingredient = ri2I;
            r2.ingredients.Add(ri1);
            r2.ingredients.Add(ri2);
            r2.directions = "fasdf sda fa sdf asdf asd fas dfa sdfasd";
            r2.RecipeID = 000002;

            Recipe r3 = new Recipe();
            r3.name = "vsadavffsd";
            RecipeIngredient ri3 = new RecipeIngredient();
            Ingredient ri3I = new Ingredient();
            ri3I.name = "usrtrggsg";
            ri3.quantity = 1;
            ri3.measurement = "ysyrrs";
            ri3.ingredient = ri3I;
            RecipeIngredient ri4 = new RecipeIngredient();
            Ingredient ri4I = new Ingredient();
            ri4I.name = "uuisrsg";
            ri4.quantity = 1;
            ri4.measurement = "hhrshrhssdr";
            ri4.ingredient = ri4I;
            r3.ingredients.Add(ri3);
            r3.ingredients.Add(ri4);
            r3.directions = "dasf asd fvr taer t ewf ewafds";
            r3.value = -1;
            r3.RecipeID = 000003;

            model.recipes = new List<Recipe>();
            model.recipes.Add(rod);
            model.recipes.Add(r2);
            model.recipes.Add(r3);
        }
        
        public void LoadMyHealthSnapshotModel(MyHealthSnapshotModel model)
        {
            User u = SecurityService.LoadCurrentUser();
            List<TrackableHealthParameter> healthParameters = DataService.LoadCurrentTrackableHealthParametersForUser(u);

            model.systolic = healthParameters[0];
            model.diastolic = healthParameters[1];
            model.waist = healthParameters[2];
            model.bmi = healthParameters[3];
            model.cholesterol = healthParameters[4];
            model.glucose = healthParameters[5];
            model.physicalActivity = healthParameters[6];
            model.restingHeart = healthParameters[7];
        }

        public void SaveDailyEntryViewModel(DailyEntryViewModel model)
        {
            Guard.ArgumentNotNull(model, "model");

            Debug.WriteLine("start DummyService.SaveDailyEntryViewModel");

            try
            {
                IEnumerable<TrackableHealthParameter> dailyHealthParameters = model.ChangedHealthParameters();

                Guard.ArgumentNotNull(dailyHealthParameters, "dailyHealthParameters");

                if (dailyHealthParameters.Any())
                {
                    var user = SecurityService.LoadCurrentUser();

                    Guard.ArgumentNotNull(user, "user");

                    foreach (var dailyHealthParameter in dailyHealthParameters)
                    {
                        var newId = DataService.InsertDailyHealthParameterForUser(dailyHealthParameter, user);

                        Guard.ArgumentNotNull(newId, "newId");

                        Debug.Assert(newId > 0);

                        dailyHealthParameter.ID = newId;
                    }
                }
            }
            catch (Exception ex)
            {
                Trace.TraceError(ex.ToString());

                throw;
            }

            Debug.WriteLine("end DummyService.SaveDailyEntryViewModel");
        }


        public void LoadRecipe(MyRecipeViewModel model)
        {
            foreach (Recipe item in model.searchResults)
            {
                if (item.RecipeID == model.selectedRecipeID) model.selectedRecipe = item;
            }
        }

        public void LoadRecipeByValue(MyRecipeViewModel model)
        {
            
        }

        /// <summary>
        /// Mock what the database would have to fill in the pages with information
        /// </summary>
        /// <param name="id"></param>
        /// <returns>The MyFoodTrackerViewModel</returns>
        public MyFoodTrackerViewModel LoadMyFoodTrackerViewModelForCurrentUser()
        {
            /*Recipe r1 = new Recipe();
            r1.RecipeID = 12;
            r1.name = "Taco Salad";
            RecipeIngredient taco = new RecipeIngredient();
            Ingredient tacoI = new Ingredient();
            tacoI.name = "taco";
            taco.quantity = 1;
            taco.measurement = "";
            taco.ingredient = tacoI;
            RecipeIngredient salad = new RecipeIngredient();
            Ingredient saladI = new Ingredient();
            saladI.name = "salad";
            salad.quantity = 1;
            salad.measurement = "";
            salad.ingredient = saladI;
            r1.ingredients.Add(taco);
            r1.ingredients.Add(salad);
            r1.directions = "Put taco and salad together.";
            r1.value = 1;

            MyFoodTrackerViewModel model = new MyFoodTrackerViewModel();
            model.searchResults = new List<Recipe>();
            model.searchResults.Add(r1);*/

            MyFoodTrackerViewModel model = new MyFoodTrackerViewModel();
            var recipeID = model.selectedRecipeID;
            var recipe = DataService.LoadMyFoodTrackerRecipes();

            return recipe;

            //return this.
        }

        /// <summary>
        /// Mock what the database would have to fill in the pages with information
        /// Load a recipe.
        /// </summary>
        /// <param name="id">MyFoodTrackerViewModel model</param>
        /// <returns>The MyFoodTrackerViewModel</returns>
        public void LoadRecipe(MyFoodTrackerViewModel model)
        {
            foreach (Recipe item in model.searchResults)
            {
                if (item.RecipeID == model.selectedRecipeID) model.selectedRecipe = item;
            }
        }

        /// <summary>
        /// Mock what the database would have to fill in the pages with information
        /// Load a recipe by a given value, such as a keyword.
        /// </summary>
        /// <param name="id">MyFoodTrackerViewModel model</param>
        /// <returns>The MyFoodTrackerViewModel</returns>
        public void LoadRecipeByValue(MyFoodTrackerViewModel model)
        {
            
        }

        public void LoadPrintableRecipe(MyRecipeViewModel model)
        {
            var recipeID = model.selectedRecipeID;
            var recipe = DataService.LoadPrintRecipe(recipeID);
            model.searchResults = recipe;
        }

        public void LoadPrintableRecipe2(MyRecipeViewModel model)
        {
            var recipeID = model.selectedRecipeID;
            var recipe = DataService.LoadPrintRecipe2(recipeID);
            model.selectedRecipe = recipe;
        }

        public UserManualModel GetUserManualModelByCurrentIndex(int sectionId)
        {
            try
            {
                Debug.WriteLine("start IBusinessService.GetUserManualModelByCurrentIndex");

                var allUserManualSections = DataService.LoadAllUserManualSections();

                var userManualSectionCollection = new UserManualSectionCollection(allUserManualSections);

                var currentUserManualSection = userManualSectionCollection.Root;

                if (sectionId > 0)
                {
                    currentUserManualSection = userManualSectionCollection.FindUserManualSectionById(sectionId);

                    var userManualContents = DataService.FindForUserManualSection(currentUserManualSection);

                    if (userManualContents.Any())
                    {
                        foreach (var userManualContent in userManualContents)
                        {
                            currentUserManualSection.AddContent(userManualContent);
                        }
                    }
                }

                Debug.WriteLine("end IBusinessService.GetUserManualModelByCurrentIndex");

                return new UserManualModel()
                {
                    CurrentUserManualSection = currentUserManualSection,
                    UserManualSectionMap = userManualSectionCollection
                };
            }
            catch (Exception ex)
            {
                Trace.TraceError(ex.ToString());

                throw;
            }
        }

        public void AddUserManualContent(UserManualModel model)
        {
            Guard.ArgumentNotNull(model, "model");

            try
            {
                Debug.WriteLine("start IBusinessService.AddUserManualContent");

                var currentUserManualContent = model.CurrentUserManualSection;

                currentUserManualContent.AddNewContent();

                Debug.WriteLine("end IBusinessService.AddUserManualContent");
            }
            catch (Exception ex)
            {
                Trace.TraceError(ex.ToString());

                throw;
            }
        }

        public void AddUserManualSection(UserManualModel model)
        {
            try
            {
                Guard.ArgumentNotNull(model, "model");

                Debug.WriteLine("start IBusinessService.AddUserManualSection");

                var userManualSectionMap = model.UserManualSectionMap;

                var currentUserManualSection = model.CurrentUserManualSection;

                var newUserManualSection = userManualSectionMap.AddNewUserManualSection(currentUserManualSection.Id);

                newUserManualSection.Title = "New Section";

                newUserManualSection.AddNewContent();

                model.CurrentUserManualSection = newUserManualSection;

                Debug.WriteLine("end IBusinessService.AddUserManualSection");
            }
            catch (Exception ex)
            {
                Trace.TraceError(ex.ToString());

                throw;
            }
        }

        public void SaveUserManualModel(UserManualModel model)
        {
            Guard.ArgumentNotNull(model, "model");

            var userManualSection = model.CurrentUserManualSection;

            Guard.ArgumentNotNull(userManualSection, "currentUserManualSection");

            try
            {
                Debug.WriteLine("start IBusinessService.SaveUserManualModel");

                if (userManualSection.Id < 1)
                {
                    userManualSection.Id = DataService.InsertUserManualSection(userManualSection);

                    foreach (var userManualContent in userManualSection.Content)
                    {
                        userManualContent.UserManualSectionId = userManualSection.Id;
                    }
                }
                else
                {
                    DataService.UpdateUserManualSection(userManualSection);
                }

                foreach (var userManualContent in userManualSection.Content)
                {
                    if (userManualContent.Id < 1)
                    {
                        userManualContent.Id = DataService.InsertUserManualContent(userManualContent);
                    }
                    else
                    {
                        DataService.UpdateUserManualContent(userManualContent);
                    }
                }

                Debug.WriteLine("end IBusinessService.SaveUserManualModel");
            }
            catch (Exception ex)
            {
                Trace.TraceError(ex.ToString());

                throw;
            }
        }



        public void FindRecipeByIDforModel(VerifyRecipeModel model)
        {
            var recipeID = model.recipeID;
            var recipe = DataService.FindRecipeByID(recipeID);
            model.Recipe = recipe;
        }




        public User LoadCurrentUser()
        {
            return SecurityService.LoadCurrentUser();
        }


        public SubmittedRecipesModel LoadSubmittedRecipesModel()
        {
            throw new NotImplementedException();
        }

        public VerifyRecipeModel LoadVerifyRecipeModel(int id)
        {
            throw new NotImplementedException();
        }

        public MyHealthSnapshotModel LoadMyHealthSnapshotModel()
        {
            throw new NotImplementedException();
        }
    }
}
